package platform.cmdexecutor;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import model.Player;
import model.Preference;
import model.inventory.InventoryPlayer;
import platform.PlatformObjectFactory;
import util.LoggingUtils;

/**
 */
public abstract class PlatformCommandExecutor {
	
	//RBB
	// Flag to indicate if the application is shutting down due to a
	// normal call to quitPlayer() or not. If not, then most likely it
	// is due to an unexpected error or an uncaught exception.
	// It is checked in player.Test.run() shutdownHook block. 
	// If true, then normal processing will resume, either an expected
	// clean shutdown or an expected restart of player.
	// If false, then it is assumed that the application has crashed, so 
	// explicit action must be taken to restart the player.
	public static boolean quitPlayerShutdown;
	
//RBB Start
/***	
	public boolean restartPlayer() {
		Player.getInstance().save();
		InventoryPlayer.getInstance().saveToXML();

		List<String> command = this.getCommandList();

		if (command.isEmpty()) {
			return false;
		}
		final ProcessBuilder builder = new ProcessBuilder(command);

		setXugglerEnvironmentVariables(builder);

		try {
			builder.start();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		this.quitPlayer();
		return true;
	}
***/
	
	/**
	 * Restarts a new Player runnable in a new process and a new jwm 
	 * without calling quitPlayer(), which would kill the existing jvm.
	 * This method is called in player.Test.runPlayer() shutdownHook
	 * block when it has been determined that the shutdown was caused by
	 * an unexpected uncaught exception or an error. This is determined
	 * by the value of the flag quitPlayerShutdown, which is only ever
	 * assigned true in quitPlayer().
	 */
	public boolean restartPlayerNoQuit() {
		System.out.println("From PlatformCommandExecutor.restartPlayerNoQuit()");
		
		LoggingUtils.logStart("PlatformCommandExecutor.restartPlayerNoQuit()");
		Player.getInstance().save();
		InventoryPlayer.getInstance().saveToXML();

		List<String> command = this.getCommandList();
		
		for(String com : command)
			System.out.println("Command for restart player: "+com);
		
		if (command.isEmpty()) {
			LoggingUtils.log(Level.SEVERE, "PlatformCommandExecutor.restartPlayerNoQuit(): "
					+ "Cannot restart Player because command List is empty.");
			return false;
		}
		
		System.out.println("From checking 1");
		
		final ProcessBuilder builder = new ProcessBuilder(command);

		setXugglerEnvironmentVariables(builder);


		try {
			System.out.println("Within try catch block:running command successfully");
			builder.start();
		} catch (IOException e) {
			LoggingUtils.log(Level.SEVERE, "System Error in PlatformCommandExecutor.restartPlayer(): "
					+ "Cannot restartPlayer.", e);
			e.printStackTrace();
			return false;
		}
		catch(Exception ex)
		{
			LoggingUtils.log(Level.SEVERE, "PlatformCommandExecutor.restartPlayer()",ex);
		}
		LoggingUtils.logEnd("PlatformCommandExecutor.restartPlayer()");
		return true;
	}

	/**
	 * Restarts a new Player runnable in a new process and a new jwm 
	 * and then it calls quitPlayer(), which kills the existing jvm.
	 * This is the normal processing strategy.
	 */
	public boolean restartPlayer() {
		
		System.out.println("restartPlayer For Checking purpose");
		
		boolean OK = restartPlayerNoQuit();
		
		System.out.println("Returnig from restartPlayer()"+OK);
		
		if (OK) {
			this.quitPlayer();
		}
		return OK;
	}

	protected List<String> getCommandList() {
		System.out.println("from command list");
		final ArrayList<String> command = new ArrayList<String>();
		final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
		File currentJar;
		try {
			currentJar = new File(player.Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());
		} catch (URISyntaxException e1) {
			// TODO Auto-generated catch block
			
			LoggingUtils.log(Level.SEVERE, "System Error in PlatformCommandExecutor .getCommandList(): "+e1.getMessage(), e1);
			
			//e1.printStackTrace();
			return command;
		}
		catch(Exception ex)
		{
			LoggingUtils.log(Level.SEVERE, "PlatformCommandExecutor.restartPlayer()",ex);
			return command;
		}
		
		LoggingUtils.logStart("platformCommandExecutor in getCommandList()");
		LoggingUtils.log(Level.SEVERE, "Linux restart");
		
		System.out.println(currentJar.getName());
		System.out.println("-Xms"+Preference.getInstance().getMemorySize()+"M");
		/* is it a jar file? */
		if (!currentJar.getName().endsWith(".jar")) {
			System.out.println(currentJar.getPath() + " is not a jar file");
			return command;
		}

		/* Build command: java -jar application.jar */
		// TODO: for windows, probably have to add Dvlcj.path for vlc
		command.add(javaBin);
		command.add("-Dvlcj.check=no");
		command.add("-Xms"+Preference.getInstance().getMemorySize()+"M");
		command.add("-Xmx"+Preference.getInstance().getMemorySize()+"M");
		command.add("-jar");
		command.add(currentJar.getPath());
		
		System.out.println(command.toString());
		
		return command;
	}

	private void setXugglerEnvironmentVariables(final ProcessBuilder builder) {
		builder.environment().put("XUGGLE_HOME", "/usr/local/xuggler");
		if (builder.environment().get("LD_LIBRARY_PATH") == null) {
			builder.environment().put("LD_LIBRARY_PATH", builder.environment().get("XUGGLE_HOME") + "/lib:");
		} else {
			builder.environment().put("LD_LIBRARY_PATH",
					builder.environment().get("XUGGLE_HOME") + "/lib:" + builder.environment().get("LD_LIBRARY_PATH"));
		}
		builder.environment().put("PATH",
				builder.environment().get("XUGGLE_HOME") + "/bin:" + builder.environment().get("PATH"));
		
		System.out.println("From set XugglerEnvironment variables");
	}

	/**
	 * Method restartComputer. hook
	 */
	public void restartComputer() {
		
	}

	/**
	 * Method quitPlayer.
	 */
	public void quitPlayer() {
		
		Thread t = new Thread(new Runnable() {

			@Override
			public void run() {
				//RBB
				LoggingUtils.logStart("run() inside PlatformCommandExecutor.quitPlayer()");
				// Set flag to true so that player.Test.runPlayer()
				// will behave as normal.
				System.out.println("Quiting payer QUITPLAYER()");
				quitPlayerShutdown = true;
				System.exit(0);
			}
		});
		t.setName("Quit Player Thread");
		LoggingUtils.logStart("Thread " + t.getName() + " in PlatformCommandExecutor.quitPlayer()");
		
		t.start();
	}

	/**
	 * Method resetPlayer.
	 */
	public void resetPlayer() {
		
		Preference.getInstance().setClearContentOnStartup(true);
		Player.getInstance().resetPlayer();
		// boolean deleted =
		// PlayerUtilities.recursiveDelete(Settings.RESOURCES_DIRECTORY);
		// PlayerUtilities.createDirectories();
		// PlayerUtilities.recursiveDelete(Settings.HTML_DIRECTORY);
		// PlayerUtilities.recursiveDelete(Settings.LOG_DIRECTORY);
		// PlayerUtilities.recursiveDelete(Settings.IMAGE_DIRECTORY);
		// PlayerUtilities.recursiveDelete(Settings.VIDEO_DIRECTORY);
		// PlayerUtilities.recursiveDelete(Settings.CSV_DIRECTORY);
		// PlayerUtilities.recursiveDelete(Settings.CONTAINERS_XML);
		// PlayerUtilities.recursiveDelete(Settings.CONTENTS_XML);
		// PlayerUtilities.recursiveDelete(Settings.PLAYLISTS_XML);
		// PlayerUtilities.recursiveDelete(Settings.INVENTORY_XML);
		// PlayerUtilities.recursiveDelete(Settings.INVENTORY_DEF_XML);

		// leave the preference xml only
		//this.restartPlayer();
		PlatformObjectFactory.getInstance().getCommandExecutor().restartPlayer();
	}

	/**
	 * hook to restart team viewer, Restart team viewer yet to implement
	 */
	public void restartTeamViewer() {

	}

	/**
	 * hook to set volume, yet to implement
	 */
	
	public void setVolume(int volume) {
	}
}
